package com.piggy.sys.service.base.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.piggy.sys.api.vo.BaseAddressVo;
import com.piggy.sys.domain.base.BaseCity;
import com.piggy.sys.domain.base.BaseDistrict;
import com.piggy.sys.domain.base.BaseProvince;
import com.piggy.sys.domain.vo.AddressTreeVo;
import com.piggy.sys.domain.vo.AddressVo;
import com.piggy.sys.mapper.base.BaseCityMapper;
import com.piggy.sys.mapper.base.BaseDistrictMapper;
import com.piggy.sys.mapper.base.BaseProvinceMapper;
import com.piggy.sys.service.base.IBaseProvinceService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 省
 */
@Service
public class BaseProvinceServiceImpl extends ServiceImpl<BaseProvinceMapper, BaseProvince> implements IBaseProvinceService {

    @Resource
    private BaseCityMapper baseCityMapper;

    @Resource
    private BaseDistrictMapper baseDistrictMapper;

    @Override
    public List<BaseAddressVo> getProvince() {
        List<BaseProvince> baseProvinceList = baseMapper.selectList(Wrappers.<BaseProvince>lambdaQuery());
        return BeanUtil.copyToList(baseProvinceList, BaseAddressVo.class);
    }

    @Override
    public List<AddressVo> getAllInfo() {
        List<BaseProvince> baseProvinceList = baseMapper.selectList(Wrappers.<BaseProvince>lambdaQuery());
        List<BaseCity> baseCityList = baseCityMapper.selectList(Wrappers.<BaseCity>lambdaQuery());
        List<BaseDistrict> baseDistrictList = baseDistrictMapper.selectList(Wrappers.<BaseDistrict>lambdaQuery());

        Map<String, List<BaseCity>> baseCityMap = baseCityList.stream().collect(Collectors.groupingBy(BaseCity::getPid));
        Map<String, List<BaseDistrict>> baseDistrictMap = baseDistrictList.stream().collect(Collectors.groupingBy(BaseDistrict::getPid));

        List<AddressVo> addressVoList = Lists.newArrayList();
        for (BaseProvince baseProvince : baseProvinceList) {
            List<BaseCity> cityList = baseCityMap.get(baseProvince.getId().toString());
            if (CollUtil.isEmpty(cityList)) {
                continue;
            }
            for (BaseCity baseCity : cityList) {
                List<BaseDistrict> districtList = baseDistrictMap.get(baseCity.getId().toString());
                if (CollUtil.isEmpty(districtList)) {
                    continue;
                }
                for (BaseDistrict baseDistrict : districtList) {
                    AddressVo addressVo = new AddressVo();
                    addressVo.setProvinceId(baseProvince.getId().toString());
                    addressVo.setCityId(baseCity.getId().toString());
                    addressVo.setDistrictId(baseDistrict.getId().toString());
                    addressVo.setProvinceName(baseProvince.getName());
                    addressVo.setAddressName(baseCity.getName() + baseDistrict.getName());
                    addressVoList.add(addressVo);
                }
            }
        }
        return addressVoList;
    }

    @Override
    public List<AddressTreeVo> getAllInfoTree() {
        List<BaseProvince> baseProvinceList = baseMapper.selectList(Wrappers.<BaseProvince>lambdaQuery());
        List<BaseCity> baseCityList = baseCityMapper.selectList(Wrappers.<BaseCity>lambdaQuery());
        List<BaseDistrict> baseDistrictList = baseDistrictMapper.selectList(Wrappers.<BaseDistrict>lambdaQuery());

        Map<String, List<BaseCity>> baseCityMap = baseCityList.stream().collect(Collectors.groupingBy(BaseCity::getPid));
        Map<String, List<BaseDistrict>> baseDistrictMap = baseDistrictList.stream().collect(Collectors.groupingBy(BaseDistrict::getPid));

        List<AddressTreeVo> addressTreeVos = new ArrayList<>(40000);
        // 遍历省份，构建树形结构
        for (BaseProvince province : baseProvinceList) {
            AddressTreeVo provinceNode = new AddressTreeVo();
            provinceNode.setText(province.getName());
            provinceNode.setLabel(province.getName());
            provinceNode.setValue(province.getId().toString());
            provinceNode.setChildren(new ArrayList<>());

            // 遍历城市，将属于该省份的城市添加到省份节点下
            List<BaseCity> cityList = baseCityMap.get(province.getId().toString());
            if (CollUtil.isEmpty(cityList)) {
                continue;
            }
            for (BaseCity city : cityList) {
                if (city.getPid().equals(province.getId().toString())) {
                    AddressTreeVo cityNode = new AddressTreeVo();
                    cityNode.setText(city.getName());
                    cityNode.setLabel(city.getName());
                    cityNode.setValue(city.getId().toString());
                    cityNode.setChildren(new ArrayList<>());

                    // 遍历区县，将属于该城市的区县添加到城市节点下
                    List<BaseDistrict> districtList = baseDistrictMap.get(city.getId().toString());
                    if (CollUtil.isEmpty(districtList)) {
                        continue;
                    }
                    for (BaseDistrict district : districtList) {
                        if (district.getPid().equals(city.getId().toString())) {
                            AddressTreeVo districtNode = new AddressTreeVo();
                            districtNode.setText(district.getName());
                            districtNode.setLabel(district.getName());
                            districtNode.setValue(district.getId().toString());
                            districtNode.setChildren(new ArrayList<>());

                            cityNode.getChildren().add(districtNode);
                        }
                    }

                    provinceNode.getChildren().add(cityNode);
                }
            }

            addressTreeVos.add(provinceNode);
        }
        return addressTreeVos;
    }
}
